package com.balance.anole.client.common.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.balance.anole.admin.to.AgentTO;
import com.balance.anole.admin.to.ShopTO;
import com.balance.anole.admin.to.StaffInfoTO;
import com.balance.anole.business.service.BusinessService;
import com.balance.anole.business.to.BusinessDateTO;
import com.balance.anole.business.to.ProductItemTO;
import com.balance.anole.business.to.ProductPriceTO;
import com.balance.anole.business.to.ProductTO;
import com.balance.anole.business.vo.ProductItemSearchTO;
import com.balance.anole.business.vo.ProductSearchTO;
import com.balance.anole.client.common.dao.BusinessDateDAO;
import com.balance.anole.client.common.dao.CodeLookDAO;
import com.balance.anole.client.common.dao.ProductDAO;
import com.balance.anole.client.common.dao.ProductItemDAO;
import com.balance.anole.client.common.dao.ShopDAO;
import com.balance.anole.client.common.dao.StaffInfoDAO;
import com.balance.anole.client.common.service.CommonService;
import com.balance.anole.client.common.service.exception.NoShopFoundException;
import com.balance.anole.common.to.CodeLookTO;
import com.balance.anole.erp.common.model.ProductItemVO;
import com.balance.anole.erp.util.ServicesCenter;
import com.balance.anole.utils.DateUtil;

public class CommonServiceImpl implements CommonService {

	private ProductItemDAO clientPdtItemDAO;
	private BusinessDateDAO clientBusinessDtDAO;
	private StaffInfoDAO clientStaffInfoDAO;
	private CodeLookDAO codeLookDAO;
	private ProductDAO clientPdtDAO;
	private ShopDAO clientShopDAO;

	public void setClientPdtDAO(ProductDAO clientPdtDAO) {
		this.clientPdtDAO = clientPdtDAO;
	}

	public void setCodeLookDAO(CodeLookDAO codeLookDAO) {
		this.codeLookDAO = codeLookDAO;
	}

	public void setClientPdtItemDAO(ProductItemDAO clientPdtItemDAO) {
		this.clientPdtItemDAO = clientPdtItemDAO;
	}

	public void setClientBusinessDtDAO(BusinessDateDAO clientBusinessDtDAO) {
		this.clientBusinessDtDAO = clientBusinessDtDAO;
	}

	public void setClientStaffInfoDAO(StaffInfoDAO clientStaffInfoDAO) {
		this.clientStaffInfoDAO = clientStaffInfoDAO;
	}

	public void setClientShopDAO(ShopDAO clientShopDAO) {
		this.clientShopDAO = clientShopDAO;
	}

	@Override
	public List<StaffInfoTO> getListOfStaffUnderSameAgent(String agentId) {
		return clientStaffInfoDAO.getListOfStaffUnderSameAgent(agentId);
	}

	@Override
	public ProductItemTO getPdtItemById(String pdtItemId) {
		ProductItemTO pdtItem = (ProductItemTO)clientPdtItemDAO.getProductItemTOByItemId(pdtItemId);
		return pdtItem;
	}

	@Override
	public List<ProductItemVO> getProductItems(ProductItemSearchTO searchTO) {
		List<ProductItemVO> pdtItemList = clientPdtItemDAO.getProductItems(searchTO);
		return pdtItemList;
	}

	@Override
	public ProductItemTO getPdtItemBySN(String sn) {
		ProductItemTO result = clientPdtItemDAO.getProductItemTOBySN(sn);
		//the price list is fetched lazily. need to convert the hibernate persistList to normal list. Otherwise UI will fail.
		if(result != null && result.getProductTO() != null && result.getProductTO().getPriceList() != null){
			List<ProductPriceTO> priceListCopy = new ArrayList<ProductPriceTO>();
			for(ProductPriceTO price : result.getProductTO().getPriceList()){
				if(price != null){
					priceListCopy.add(price);
				}
			}
			result.getProductTO().setPriceList(priceListCopy);
		}

		return result;
	}

	@Override
	public CodeLookTO getCodeLookTOByCodeTypeAndCodeId(String codeTypeId,
			String codeId) {
		return codeLookDAO.getCodeLookTOByCodeTypeAndCodeId(codeTypeId, codeId);
	}

	@Override
	public BusinessDateTO getBusinessDate() {
		return clientBusinessDtDAO.getCurrentBusinessDate();
	}

	public boolean synchronizeBusinessDate(){
		boolean warning = false;
		BusinessDateTO newBusinessDate = new BusinessDateTO();
		BusinessDateTO clientBusinessDate = clientBusinessDtDAO.getCurrentBusinessDate();
		//try to synchronize business date from server.
		try{
			BusinessService bs = ServicesCenter.getServicesCenter().getService(BusinessService.class);
			BusinessDateTO serverBusinessDate = bs.getCurrentBusinessDate();

			if(serverBusinessDate != null){
				if (clientBusinessDate == null
						|| !DateUtil.format(
								serverBusinessDate.getBusinessDate(),
								DateUtil.DEFALT_FORMAT_DATE).equalsIgnoreCase(
								DateUtil.format(clientBusinessDate
										.getBusinessDate(),
										DateUtil.DEFALT_FORMAT_DATE))) {
					newBusinessDate.setBusinessDate(serverBusinessDate
							.getBusinessDate());
					newBusinessDate.setPreBusinessDate(serverBusinessDate
							.getPreBusinessDate());
					clientBusinessDtDAO.insertOrUpdateBusinessDate(newBusinessDate);
				}
				//if current business date doesn't equal to system date, need warn user.
				if (!DateUtil.format(serverBusinessDate.getBusinessDate(),
						DateUtil.DEFALT_FORMAT_DATE).equalsIgnoreCase(
						DateUtil.format(DateUtil.getSystemCurrentDate(),
								DateUtil.DEFALT_FORMAT_DATE))) {
					warning = true;
				}
			}
		}catch(Exception e){
			//create business date using client system date.
			newBusinessDate.setBusinessDate(DateUtil.getSystemCurrentDate());
			newBusinessDate.setPreBusinessDate(clientBusinessDate.getBusinessDate());
			clientBusinessDtDAO.insertOrUpdateBusinessDate(newBusinessDate);
			warning = true;
		}

		return warning;
	}

	@Override
	public Map<String, List<CodeLookTO>> getCodeLooksByCodeTypes(
			String[] codeTypeIds) {
		if(codeTypeIds == null || codeTypeIds.length  == 0){
			return null;
		}

		Map<String, List<CodeLookTO>> codeLooksByCodeTypes = new HashMap<String, List<CodeLookTO>>();
		for(int i=0;i<codeTypeIds.length;i++){
			List<CodeLookTO> l = codeLookDAO.getCodeLookTOsByCodeType(codeTypeIds[i]);
			codeLooksByCodeTypes.put(codeTypeIds[i], l);
		}
		return codeLooksByCodeTypes;
	}

	@Override
	public List<ProductTO> getProducts(ProductSearchTO searchTO) {
		return clientPdtDAO.getProducts(searchTO);
	}

	@Override
	public ShopTO getShop(AgentTO agentTO) {
		ShopTO shop = clientShopDAO.getShopTO(agentTO);
		if(shop == null){
			throw new NoShopFoundException("No shop found for " + agentTO.getAgentName() + " or it is not a shop.");
		}
		return shop;
	}

	@Override
	public BusinessDateTO getBusinessDateByCurrentBusinessDate(
			Date currentBusinessDate) {
		return clientBusinessDtDAO.getBusinessDateByCurrentBusinessDate(currentBusinessDate);
	}

	@Override
	public void insertOrUpdateBusinessDate(BusinessDateTO businessDateTO) {
		clientBusinessDtDAO.insertOrUpdateBusinessDate(businessDateTO);
	}
}
